package com.example.demo.controller;

import com.example.demo.vo.RequestParams;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.avformat;
import org.bytedeco.javacpp.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


@Controller
@Slf4j
public class MainThreadsFFmpegFrameGrabber {
    @PostMapping("/videoCut")
    @ResponseBody
    public String videoCut(@RequestBody RequestParams data) {
        log.info("Start videoCut...");
        List<String> orgVideoPaths = new ArrayList<>();
        int skipOrAppoint = data.getSkipOrAppoint();//1跳过2指定
        String specialNames = data.getSpecialNames();
        String[] specialNamesArray = null;

        List specialNamesList = null;
        if (skipOrAppoint == 1 ||skipOrAppoint == 2) {//特殊处理
            specialNamesArray = specialNames.split(",");
            specialNamesList = Arrays.asList(specialNamesArray);
        }

        List<String> videoPaths = new ArrayList<>();
        Path directoryPath = Paths.get(data.getVideoPath()); // 替换为你的目录路径

        try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
            for (Path file : stream) {
                String filePath = file.toString();
                if (!filePath.endsWith(".mp4")) {
                    continue;
                }
                if (skipOrAppoint == 1) {//跳过
                    if (specialNamesList.contains(filePath.substring(filePath.lastIndexOf(System.getProperty("file.separator")) + 1))) {
                        continue;
                    }
                }
                if (skipOrAppoint == 2) {//指定
                    if (!specialNamesList.contains(filePath.substring(filePath.lastIndexOf(System.getProperty("file.separator")) + 1))) {
                        continue;
                    }
                }
                videoPaths.add(filePath);
            }
        } catch (IOException | DirectoryIteratorException e) {
            e.printStackTrace();
        }


        int groupSize = data.getGroupSize();

        ExecutorService executor = Executors.newFixedThreadPool(data.getThreadUse());
        for (int i = 0; i < videoPaths.size(); i += groupSize) {
            int end = Math.min(i + groupSize, videoPaths.size());

            // 创建一个子列表，其中包含当前组的文件
            List<String> fileGroup = videoPaths.subList(i, end);
            final CountDownLatch latch = new CountDownLatch(fileGroup.size());


            for (int j = 0; j < fileGroup.size(); j++) {

                String videoPath = fileGroup.get(j);
                log.info("Processing video: {}", videoPath);
                File video = null;
                try {
                    video = ResourceUtils.getFile(videoPath);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    latch.countDown(); // 即使文件未找到，也要递减计数器
                    continue;
                }

                String outputDirPath = data.getPicSavePath(); // 输出目录

                File finalVideo = video;
                executor.execute(() -> {
                    try {
                        getVideoPicEveryTenMinutes(finalVideo, outputDirPath);
                    } finally {
                        latch.countDown(); // 确保无论任务是否成功完成，都递减计数器
                    }
                });
            }
            // 等待当前组的所有任务完成
            try {
                latch.await(); // 阻塞，直到计数器减到0
            } catch (InterruptedException e) {
                // 如果等待被中断，则应该优雅地处理中断
                Thread.currentThread().interrupt();
                // 可能还需要关闭线程池或处理其他清理工作
            }

        }
        executor.shutdown();
        log.info("Finish videoCut.");
        return "success";

    }

    /**
     * 虽然慢但海康等视频截图可以成功
     * @param video
     * @param outputDirPath
     */
    public static void getVideoPicEveryTenMinutesSlow(File video, String outputDirPath) {
        String originalFileName = video.getName();
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
        try {
            ff.setOption("pixel_format", "bgr24"); // 尝试使用 "bgr24"
            ff.start();
            log.info("{}截图开始", originalFileName);
            // 确保输出目录存在
            File outputDir = new File(outputDirPath);
            if (!outputDir.exists()) {
                outputDir.mkdirs();
            }

            // 设置截图的时间间隔为10分钟（以毫秒为单位）
            long intervalInMilliseconds = 10L * 60 * 1000; // 10 minutes in milliseconds
            long lastCaptureTimeMillis = 0; // 初始化为0，确保第一个帧能被捕获

            Frame frame;
            while ((frame = ff.grabFrame()) != null) {
                if (frame.image == null) {
                    continue; // 如果frame不包含图像数据，则跳过此次循环
                }

                // 以下代码需要修改
                long currentTimeMillis = frame.timestamp / 1000; // 修正时间单位为毫秒

                // 检查是否需要截图
                if (currentTimeMillis - lastCaptureTimeMillis >= intervalInMilliseconds) {
                    lastCaptureTimeMillis = currentTimeMillis; // 更新最后截图的时间

                    // 转换帧为BufferedImage
                    Java2DFrameConverter converter = new Java2DFrameConverter();
                    BufferedImage srcImage = converter.getBufferedImage(frame);

                    if (srcImage == null) {
                        log.error("Failed to convert frame to BufferedImage!");
                        continue; // 如果转换失败，打印错误信息并跳过此次循环
                    }

                    // 使用与视频帧时间戳相关的名称来保存截图（可选）
                    String parentName = video.getParentFile().getName();
                    long videoTimeInSeconds = currentTimeMillis / 1000;
                    String fileName = parentName + "_" + originalFileName + "_screenshot_" + videoTimeInSeconds + ".jpg";
                    File picFile = new File(outputDir, fileName);
                    ImageIO.write(srcImage, "jpg", picFile);

                    // 输出截图信息（可选）
//                    log.info("Screenshot saved: " + picFile.getAbsolutePath());
                }
            }
            log.info("{}截图完成", originalFileName);

            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /***
     * 设置定位点进行跳转截图，一般视频可行，海康等视频有问题
     * @param video
     * @param outputDirPath
     */
    public static void getVideoPicEveryTenMinutes(File video, String outputDirPath) {
        // 加载 FFmpeg 库
        avcodec.avcodec_register_all();
        avformat.av_register_all();
        avutil.av_log_set_level(avutil.AV_LOG_QUIET);

        String originalFileName = video.getName();
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(video);
        try {
            ff.start();
            File outputDir = new File(outputDirPath);
            if (!outputDir.exists()) {
                outputDir.mkdirs();
            }
            // 获取视频的总时长（以秒为单位）
            long totalSeconds = ff.getLengthInTime() / 1000000;

            // 每隔10分钟截取截图
            for (long currentSecond = 0; currentSecond <= totalSeconds; currentSecond += 10 * 60) {
                // 设置时间戳（以微秒为单位）
                long timeStampInSeconds = currentSecond * 1000000L;
                ff.setTimestamp(timeStampInSeconds);
// 等待5秒钟，让帧稳定
                Thread.sleep(5000);
                // 抓取帧
                Frame frame = ff.grabImage();


                if (frame != null) {
                    Java2DFrameConverter converter = new Java2DFrameConverter();
                    BufferedImage bufferedImage = converter.getBufferedImage(frame);

                    // 生成文件名
                    int humanMinutes = (int) (currentSecond / 60);
                    String parentName = video.getParentFile().getName();
                    String fileName = parentName + "_" +originalFileName + "_screenshot_" + humanMinutes + ".jpg";
                    File picFile = new File(outputDir, fileName);

                    // 保存截图
                    javax.imageio.ImageIO.write(bufferedImage, "jpg", picFile);
                }
            }

            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}